//
//  ZLNumberField.swift
//  nf-ios
//
//  Created by itzhaolei on 2021/9/7.
//

import Foundation

open class ZLNumberField: UITextField {
    
    // 配置
    private lazy var realityHeight: CGFloat = {
        ZLLocalAutoScale(200.0)
    }()
    private let bgColor: UIColor = .init(red: 0.82, green: 0.82, blue: 0.84, alpha: 1.0)
    private let forbiddenColor: UIColor = .init(red: 0.65, green: 0.65, blue: 0.67, alpha: 1.0)
    private let touchColor: UIColor = .init(red: 0.78, green: 0.78, blue: 0.80, alpha: 1.0)
    
    private lazy var unitView: UIView = {
        let view = UIView(frame: .init(x: 0, y: 0, width: UIScreen.main.bounds.width, height: realityHeight + 80.0))
        view.backgroundColor = bgColor
        addKeys(unitView: view)
        return view
    }()
    private var changed: ((_ text: String) -> Void)?
    private var done: ((_ text: String) -> Void)?
    private var items: [UIButton] = []
    public init(frame: CGRect, changed: ((_ text: String) -> Void)?, done: ((_ text: String) -> Void)?) {
        self.changed = changed
        self.done = done
        super.init(frame: frame)
        self.inputView = unitView
    }
    
    open override var text: String? {
        didSet {
            changed?(text ?? "")
        }
    }
    
    required public init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        return false
    }
    
    @discardableResult
    open override func becomeFirstResponder() -> Bool {
        let isCan = super.becomeFirstResponder()
        return isCan
    }
        
}

private extension ZLNumberField {
    
    func ZLLocalAutoScale(_ value: CGFloat) -> CGFloat {
        let referWidth: CGFloat = 375.0
        let referHeight: CGFloat = 217.0
        let realityWidth: CGFloat = UIScreen.main.bounds.width
        let realityHeight: CGFloat = realityWidth * (referHeight / referWidth)
        let scale = ((realityHeight + realityWidth) / (referHeight + referWidth)) * value
        return scale
    }
        
    func addKeys(unitView: UIView) {
        let names: [String] = ["1","2","3","4","5","6","7","8","9","","0",""]
        let screenWidth: CGFloat = UIScreen.main.bounds.width
        let space: CGFloat = ZLLocalAutoScale(7.0)
        for index in 0..<names.count {
            let minItemWidth: CGFloat = (screenWidth - space * 4) / 3
            let minItemHeight: CGFloat = (realityHeight - space * 4) / 4
            let button = UIButton(frame: .init(x: space + (minItemWidth + space) * CGFloat((index % 3)), y: space + (minItemHeight + space) * CGFloat((index / 3)), width: minItemWidth, height: minItemHeight))
            button.backgroundColor = .white
            button.isEnabled = true
            if (index == names.count - 1) {
                let image = Resources.image("清除")
                button.setImage(image, for: .normal)
                button.addTarget(self, action: #selector(deleteAction(_:)), for: .touchUpInside)
            }else if (index == names.count - 3) {
                let image = Resources.image("键盘")
                button.setImage(image, for: .normal)
                button.addTarget(self, action: #selector(closeAction(_:)), for: .touchUpInside)
            }else {
                button.setTitle(names[index], for: .normal)
                button.titleLabel?.font = .boldSystemFont(ofSize: ZLLocalAutoScale(18.0))
                button.setTitleColor(.black, for: .normal)
                button.addTarget(self, action: #selector(itemAction(_:)), for: .touchUpInside)
            }
            button.layer.cornerRadius = 6.0
            unitView.addSubview(button)
            items.append(button)
        }
    }
    
    @objc func closeAction(_ sender: UIButton) {
        clickAnimation(sender)
        checkValidityAndRepair()
        resignFirstResponder()
    }
    
    /// 检查有效性并修复
    func checkValidityAndRepair() {
        self.text = "\(Int64(text ?? "") ?? 0)"
    }
    
    @objc func deleteAction(_ sender: UIButton) {
        clickAnimation(sender)
        let fieldText: NSString = ((text ?? "") as NSString)
        let location = self.offset(from: beginningOfDocument, to: selectedTextRange?.start ?? .init())
        if fieldText.length > 0 && location > 0 {
            self.text = fieldText.replacingCharacters(in: .init(location: location - 1, length: 1), with: "")
            // 回滚光标为初始位置
            let begin = beginningOfDocument
            let start = position(from: begin, offset: 0)
            let range = textRange(from: start ?? .init(), to: start ?? .init())
            selectedTextRange = range
            // 调整偏移量
            var currentOffset = offset(from: endOfDocument, to: selectedTextRange?.end ?? .init())
            currentOffset += (location - 1)
            let newPos = position(from: endOfDocument, offset: currentOffset)
            selectedTextRange = textRange(from: newPos ?? .init(), to: newPos ?? .init())
        }
    }
    
    @objc func itemAction(_ sender: UIButton) {
        clickAnimation(sender)
        let fieldText: NSString = ((text ?? "") as NSString)
        let location = offset(from: beginningOfDocument, to: selectedTextRange?.start ?? .init())
        let importText: String = sender.titleLabel?.text ?? ""
        self.text = "\(Int64(fieldText.replacingCharacters(in: .init(location: location, length: 0), with: importText)) ?? 0)"
        // 回滚光标为初始位置
        let begin = beginningOfDocument
        let start = position(from: begin, offset: 0)
        let range = textRange(from: start ?? .init(), to: start ?? .init())
        selectedTextRange = range
        // 调整偏移量
        let selectedRange = selectedTextRange
        var currentOffset = offset(from: endOfDocument, to: selectedRange?.end ?? .init())
        currentOffset += (location + importText.count)
        let newPos = position(from: endOfDocument, offset: currentOffset)
        selectedTextRange = textRange(from: newPos ?? .init(), to: newPos ?? .init())
    }
    
    func clickAnimation(_ sender: UIButton) {
        sender.backgroundColor = touchColor
        weak var weakSender = sender
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.05, execute: {
            weakSender?.backgroundColor = .white
        })
    }
    
}
